# 两个涨夹一个跌线
# 两阳夹一阴:由三根K线构成,第一根为阳线,第二根为阴线,第三根为阳线
# （1）两阳夹一阴由3根K线组成。第一根K线和第三根K线为阳线，第二根K线为阴线
# （2）两阳夹一阴的三根K线实体要略长一些，而且长短答题相当
# （3）处在高位的两阳夹一阴，阴线的开盘价和阳线的收盘价接近
# （4）处在低位和上涨途中的两阳夹一阴，阴线的收盘价和阳线的开盘价接近
import json
import os
from decimal import Decimal
from utils import read_config

stock_path = read_config.base_path
from utils import date_util, k_util, select_util, chart_util
from service.data_service import stock_dict

# 参数调整
min_compare_amplitude = 0.005  # 最小振幅长度
max_compare_amplitude = 0.04  # 最大振幅长度
min_close_line = 0.0001  # 最小接近幅度
max_close_line = 0.002  # 最大接近幅度
max_ahead_days = 0  # 最大提前天数
min_ahead_days = 0  # 最大提前天数

today_str = date_util.get_format_date_str("%Y-%m-%d")
base_result_path = stock_path + '\\result\\双阳夹阴\\' + today_str + '\\'
view_file_path = base_result_path + '\\view\\'

if not os.path.exists(view_file_path):
    os.makedirs(view_file_path)  # 没有创建文件夹

select_stock_list = {}


# 估算阴阳
def estimate_yin_yang(stock, klines, ahead_days, compare_amplitude, close_line, result_file):
    # print("估算阴阳,股票编码" + stock + '其他信息' + str(stock_dict[stock]))
    klines_len = len(klines)
    if klines_len < (ahead_days + 3):
        return
    new_klines = []
    new_klines.append(klines[klines_len - 1 - ahead_days])
    new_klines.append(klines[klines_len - 2 - ahead_days])
    new_klines.append(klines[klines_len - 3 - ahead_days])
    # （1）两阳夹一阴由3根K线组成。第一根K线和第三根K线为阳线，第二根K线为阴线
    # print(new_klines)
    if judge_yin_yang(Decimal(new_klines[0].split(',')[1]), Decimal(new_klines[0].split(',')[2])) and \
            judge_yin_yang(Decimal(new_klines[2].split(',')[1]), Decimal(new_klines[2].split(',')[2])) and not \
            judge_yin_yang(Decimal(new_klines[1].split(',')[1]), Decimal(new_klines[1].split(',')[2])):
        print('股票:' + stock + ' (1)两阳夹一阴由3根K线组成。第一根K线和第三根K线为阳线，第二根K线为阴线')
        # （2）两阳夹一阴的三根K线实体要略长一些，而且长短大体相当
        k_info_one = new_klines[0].split(',')
        k_info_two = new_klines[1].split(',')
        k_info_thr = new_klines[2].split(',')
        amplitude_one = (Decimal(k_info_one[2]) - Decimal(k_info_one[1])) / Decimal(k_info_one[1])
        amplitude_two = (Decimal(k_info_two[1]) - Decimal(k_info_two[2])) / Decimal(k_info_two[1])
        amplitude_thr = (Decimal(k_info_thr[2]) - Decimal(k_info_thr[1])) / Decimal(k_info_thr[1])
        print(
            str(amplitude_one) + ">>" + str(amplitude_one) + ">>" + str(amplitude_one) + ">>" + str(compare_amplitude))
        if (amplitude_one > compare_amplitude) and \
                (amplitude_two > compare_amplitude) and \
                (amplitude_thr > compare_amplitude):
            print('股票:' + stock + ' (2)两阳夹一阴的三根K线实体要略长一些，而且长短大体相当')
            # （3）处在高位的两阳夹一阴，阴线的开盘价和阳线的收盘价接近
            close_one = abs((float(k_info_two[1]) - float(k_info_thr[2])) / float(k_info_thr[2]))
            if close_one < close_line:
                print('股票:' + stock + ' (3)处在高位的两阳夹一阴，阴线的开盘价和阳线的收盘价接近')
                # （4）处在低位和上涨途中的两阳夹一阴，阴线的收盘价和阳线的开盘价接近
                close_two = abs((float(k_info_two[2]) - float(k_info_one[1])) / float(k_info_one[1]))
                if close_two < close_line:
                    print('股票:' + stock + ' (4)处在低位和上涨途中的两阳夹一阴，阴线的收盘价和阳线的开盘价接近')
                    select_stock_list[stock] = '1'
                    result_file.write('股票:' + stock + ' 通过两阳夹阴' + '\t')
                    result_file.write(str(ahead_days) + '天前，对比振幅：')
                    result_file.write(str(compare_amplitude))
                    result_file.write('，接近振幅' + str(close_line))
                    result_file.write('，日期' + k_info_one[0] + '\n')
                    return 1


# 递归阴阳
def recursive_yin_yang(stock):
    print("递归阴阳,股票编码" + stock + '其他信息' + str(stock_dict[stock]))
    recursive_result = open(view_file_path + '\\' + stock + '.txt', mode='w', encoding='utf-8')
    klines = k_util.day_k(stock, str(stock_dict[stock]['name']), str(stock_dict[stock]['exchange']))
    diff_amplitude = int((max_compare_amplitude - min_compare_amplitude) * 1000) + 1
    diff_close = int((max_close_line - min_close_line) * 4000) + 1
    diff_days = int((max_ahead_days - min_ahead_days)) + 1
    flag = 0
    for amplitude in range(diff_amplitude):
        c_amplitude = round(max_compare_amplitude - (amplitude / 1000), 3)
        for close in range(diff_close):
            c_close = round(min_close_line + (close / 4000), 4)
            for day in range(diff_days):
                if flag == 0:
                    flag = estimate_yin_yang(stock, klines,
                                             day + min_ahead_days,
                                             c_amplitude, c_close,
                                             recursive_result)
                if flag == 1:
                    msg = '股票:' + stock + ' 通过两阳夹阴' + '\t' + str(day + min_ahead_days) + \
                          '天前，对比振幅：' + str(c_amplitude) + '，接近振幅' + str(c_close) + '，日期' + klines[0] + '\n'
                    recursive_result.write(msg)
    recursive_result.close()


def judge_yin_yang(kai_pan, shou_pan):
    # 阳线是证券市场上指收盘价高于开盘价的K线
    if shou_pan >= kai_pan:
        return 1
    return 0


def select_dict():
    return select_util.select_doc()


def select_cal():
    deal_cal_flag = input('计算方式***0.当前1.昨天(默认)2.输入几天前:')
    if deal_cal_flag == '' or int(deal_cal_flag) == 1:
        return 1
    return int(deal_cal_flag)


def yin_yang_main():
    # 选择要处理的文件
    select_stock = select_dict()
    select_the_stock_yin_yang(select_stock)


def select_all_yin_yang():
    stock_file = open(stock_path + '\\config\\0.股票信息', encoding='utf-8')
    select_stock = {}
    while 1:
        line = stock_file.readline()[:-1]
        if line == '':
            break
        line_j = json.loads(line.replace("\'", "\""))
        select_stock[line_j['code']] = line_j
    stock_file.close()
    select_the_stock_yin_yang(select_stock)


def select_the_stock_yin_yang(select_stock):
    # 估算结果
    count = 0
    for s_code in select_stock:
        recursive_yin_yang(s_code)
        count += 1
        if count % 200 == 0:
            del_result_file()
    validation_dict = del_result_file()
    # 生成视图
    for code in validation_dict:
        if code[0:3] == '300' or code[0:3] == '688':
            continue
        print(code + "开始k")
        chart_util.day_k_with_path(code, 80, view_file_path)
        print(code + "结束k")
        print(code + "开始macd")
        chart_util.MACD_with_path(code, code + stock_dict[code]['name'].replace('*', '') + '-MACD', view_file_path)
        print(code + "结束macd")


def del_result_file():
    # 删除空结果
    validation_list = []
    for root, dirs, files in os.walk(view_file_path):
        for file in files:
            src_file = os.path.join(root, file)
            if os.path.getsize(src_file) == 0:
                os.remove(src_file)
            else:
                validation_list.append(file.split('.')[0])
    # 去重:
    validation_dict = {}
    for code in validation_list:
        validation_dict[code[0:6]] = 1

    # 生成验证文件
    validation_result = open(base_result_path + '\\验证' + today_str + '.txt', mode='w', encoding='utf-8')
    for s_code in validation_dict:
        validation_result.write(str(stock_dict[s_code]) + '\n')
    validation_result.close()

    # 生成精选文件
    validation_result = open(base_result_path + '\\精选' + today_str + '.txt', mode='w', encoding='utf-8')
    for s_code in validation_dict:
        if s_code[0:3] == '300' or s_code[0:3] == '688':
            continue
        validation_result.write(str(stock_dict[s_code]) + '\n')
    validation_result.close()
    return validation_dict


if __name__ == '__main__':
    print('********两阳夹阴 start*******')
    yin_yang_main()
    print('********两阳夹阴 end*******')
